package handler

import (
	"blog_go/internal/model"
	"blog_go/internal/service"
	"blog_go/pkg/helper/resp"
	"net/http"

	"github.com/gin-gonic/gin"
	"go.uber.org/zap"
)

type ArticleHandler interface {
	QueryArticleByArticleId(ctx *gin.Context)
	QueryUserArticle(ctx *gin.Context)
	QueryAllArticle(ctx *gin.Context)
	QueryArticle(ctx *gin.Context)
	QueryCollectedArticle(ctx *gin.Context)
	QueryArticles(ctx *gin.Context)
	AddArticle(ctx *gin.Context)
	AddMdArticle(ctx *gin.Context)
	UpdateArticle(ctx *gin.Context)
	UpdateMdArticle(ctx *gin.Context)
	UpdateUploadFile(ctx *gin.Context)
	DelArticle(ctx *gin.Context)
	LikeArticle(ctx *gin.Context)
	DisLikeArticle(ctx *gin.Context)
	ViewArticle(ctx *gin.Context)
	ReviewArticle(ctx *gin.Context)
	ReviewAllArticle(ctx *gin.Context)
	CollectArticle(ctx *gin.Context)
	MoveArticle(ctx *gin.Context)
}

type articleHandler struct {
	*Handler
	articleService service.ArticleService
}

func NewArticleHandler(handler *Handler, articleService service.ArticleService) ArticleHandler {
	return &articleHandler{
		Handler:        handler,
		articleService: articleService,
	}
}

// 富文本上传文件
func (h *articleHandler) UpdateUploadFile(ctx *gin.Context) {
	files, _ := ctx.MultipartForm()

	h.logger.Info("UpdateUploadFile attempted")

	data, err := h.articleService.UpdateUploadFile(files)

	if err != nil {
		h.logger.Error("UpdateUploadFile failed", zap.Any("error", err))
		resp.HandleError(ctx, http.StatusInternalServerError, 1, err.Error(), nil)
		return
	}

	resp.HandleSuccess(ctx, data)
}

// 富文本发布文章
func (h *articleHandler) AddArticle(ctx *gin.Context) {
	var article model.ArticleView

	if err := ctx.ShouldBind(&article); err != nil {
		h.logger.Warn("AddArticle", zap.Any("error", err))
		resp.HandleError(ctx, http.StatusBadRequest, 1, err.Error(), nil)
		return
	}

	userId := GetUserIdFromCtx(ctx)
	if userId == 0 {
		resp.HandleError(ctx, http.StatusBadRequest, 1, "token错误", nil)
		return
	}

	h.logger.Info("AddArticle attempted", zap.Any("userId", userId), zap.Any("title", article.Title))

	err := h.articleService.AddArticle(article, userId)

	if err != nil {
		h.logger.Error("AddArticle failed", zap.Int("userId", userId), zap.Error(err))
		resp.HandleError(ctx, http.StatusInternalServerError, 1, err.Error(), nil)
		return
	}

	resp.HandleSuccess(ctx, nil)
}

// markdown发布文章
func (h *articleHandler) AddMdArticle(ctx *gin.Context) {
	var article model.ArticleView

	if err := ctx.ShouldBind(&article); err != nil {
		h.logger.Warn("AddMdArticle", zap.Any("error", err))
		resp.HandleError(ctx, http.StatusBadRequest, 1, err.Error(), nil)
		return
	}

	userId := GetUserIdFromCtx(ctx)
	if userId == 0 {
		resp.HandleError(ctx, http.StatusBadRequest, 1, "token错误", nil)
		return
	}

	h.logger.Info("AddMdArticle attempted", zap.Any("userId", userId), zap.Any("title", article.Title))

	err := h.articleService.AddMdArticle(article, userId)

	if err != nil {
		h.logger.Error("AddMdArticle failed", zap.Int("userId", userId), zap.Error(err))
		resp.HandleError(ctx, http.StatusInternalServerError, 1, err.Error(), nil)
		return
	}

	resp.HandleSuccess(ctx, nil)
}

// 修改富文本文章
func (h *articleHandler) UpdateArticle(ctx *gin.Context) {
	var article model.ArticleView

	if err := ctx.ShouldBind(&article); err != nil {
		h.logger.Warn("UpdateArticle", zap.Any("error", err))
		resp.HandleError(ctx, http.StatusBadRequest, 1, err.Error(), nil)
		return
	}

	userId := GetUserIdFromCtx(ctx)
	if userId == 0 {
		resp.HandleError(ctx, http.StatusBadRequest, 1, "token错误", nil)
		return
	}

	h.logger.Info("UpdateArticle attempted", zap.Any("articleId", article.ArticleId), zap.Any("title", article.Title))

	err := h.articleService.UpdateArticle(article, userId)

	if err != nil {
		h.logger.Error("UpdateArticle failed", zap.Any("articleId", article.ArticleId), zap.Any("error", err))
		resp.HandleError(ctx, http.StatusInternalServerError, 1, err.Error(), nil)
		return
	}

	resp.HandleSuccess(ctx, nil)
}

// 修改md文章
func (h *articleHandler) UpdateMdArticle(ctx *gin.Context) {
	var article model.ArticleView

	if err := ctx.ShouldBind(&article); err != nil {
		h.logger.Warn("UpdateMdArticle", zap.Any("error", err))
		resp.HandleError(ctx, http.StatusBadRequest, 1, err.Error(), nil)
		return
	}

	userId := GetUserIdFromCtx(ctx)
	if userId == 0 {
		resp.HandleError(ctx, http.StatusBadRequest, 1, "token错误", nil)
		return
	}

	h.logger.Info("UpdateMdArticle attempted", zap.Any("articleId", article.ArticleId), zap.Any("title", article.Title))

	err := h.articleService.UpdateMdArticle(article, userId)

	if err != nil {
		h.logger.Error("UpdateMdArticle failed", zap.Any("articleId", article.ArticleId), zap.Any("error", err))
		resp.HandleError(ctx, http.StatusInternalServerError, 1, err.Error(), nil)
		return
	}

	resp.HandleSuccess(ctx, nil)
}

// 删除文章
func (h *articleHandler) DelArticle(ctx *gin.Context) {
	var params struct {
		ArticleIds []int `json:"articleIds"`
	}

	if err := ctx.ShouldBind(&params); err != nil {
		h.logger.Warn("DelArticle", zap.Any("error", err))
		resp.HandleError(ctx, http.StatusBadRequest, 1, err.Error(), nil)
		return
	}

	userId := GetUserIdFromCtx(ctx)
	if userId == 0 {
		resp.HandleError(ctx, http.StatusBadRequest, 1, "token错误", nil)
		return
	}

	userType := GetUserTypeFromCtx(ctx)
	if userType == -1 {
		resp.HandleError(ctx, http.StatusBadRequest, 1, "token错误", nil)
		return
	}

	h.logger.Info("DelArticle attempted", zap.Any("articleIds", params.ArticleIds), zap.Any("userId", userId))

	err := h.articleService.DelArticle(params.ArticleIds, userId, userType)

	if err != nil {
		h.logger.Error("DelArticle failed", zap.Any("articleIds", params.ArticleIds), zap.Any("error", err))
		resp.HandleError(ctx, http.StatusInternalServerError, 1, err.Error(), nil)
		return
	}

	resp.HandleSuccess(ctx, nil)
}

// 根据标题、内容，模糊查询
func (h *articleHandler) QueryArticles(ctx *gin.Context) {
	var params struct {
		KeyWords string `form:"keyWords"`
		Page     int    `form:"page"`
		PageSize int    `form:"pageSize"`
		UserId   int    `form:"userId"`
	}

	if err := ctx.ShouldBind(&params); err != nil {
		h.logger.Warn("QueryArticles", zap.Any("error", err))
		resp.HandleError(ctx, http.StatusBadRequest, 1, err.Error(), nil)
		return
	}

	h.logger.Info("QueryArticles attempted", zap.Any("params", params))

	data, err := h.articleService.QueryArticles(params.KeyWords, params.Page, params.PageSize, params.UserId)

	if err != nil {
		h.logger.Error("QueryArticles failed", zap.Any("keyWords", params.KeyWords), zap.Any("error", err))
		resp.HandleError(ctx, http.StatusInternalServerError, 1, err.Error(), nil)
		return
	}

	resp.HandleSuccess(ctx, data)
}

// 获取文章详情
func (h *articleHandler) QueryArticleByArticleId(ctx *gin.Context) {
	var params struct {
		ArticleId int `form:"articleId" binding:"required"`
		UserId    int `form:"userId"`
	}

	if err := ctx.ShouldBind(&params); err != nil {
		h.logger.Warn("QueryArticleByArticleId", zap.Any("error", err))
		resp.HandleError(ctx, http.StatusBadRequest, 1, err.Error(), nil)
		return
	}

	h.logger.Info("QueryArticleByArticleId attempted", zap.Int("articleId", params.ArticleId))

	data, err := h.articleService.QueryArticleByArticleId(params.ArticleId, params.UserId)

	if err != nil {
		h.logger.Error("QueryArticleByArticleId failed", zap.Any("articleId", params.ArticleId), zap.Any("error", err))
		resp.HandleError(ctx, http.StatusInternalServerError, 1, err.Error(), nil)
		return
	}

	resp.HandleSuccess(ctx, data)
}

// 获取分类下的文章
func (h *articleHandler) QueryAllArticle(ctx *gin.Context) {
	var params struct {
		CategoryId int `form:"categoryId"`
		TagId      int `form:"tagId"`
		UserId     int `form:"userId"`
		Page       int `form:"page"`
		PageSize   int `form:"pageSize"`
	}

	if err := ctx.ShouldBind(&params); err != nil {
		h.logger.Warn("QueryAllArticle", zap.Any("error", err))
		resp.HandleError(ctx, http.StatusBadRequest, 1, err.Error(), nil)
		return
	}

	h.logger.Info("QueryAllArticle attempted", zap.Any("params", params))

	data, err := h.articleService.QueryAllArticle(params.CategoryId, params.TagId, params.UserId, params.Page, params.PageSize)

	if err != nil {
		h.logger.Error("QueryAllArticle failed", zap.Any("error", err))
		resp.HandleError(ctx, http.StatusInternalServerError, 1, err.Error(), nil)
		return
	}

	resp.HandleSuccess(ctx, data)
}

// 获取个人文章
func (h *articleHandler) QueryArticle(ctx *gin.Context) {
	userId := GetUserIdFromCtx(ctx)
	if userId == 0 {
		resp.HandleError(ctx, http.StatusBadRequest, 1, "token错误", nil)
		return
	}

	userType := GetUserTypeFromCtx(ctx)
	if userType == -1 {
		resp.HandleError(ctx, http.StatusBadRequest, 1, "token错误", nil)
		return
	}

	h.logger.Info("QueryArticle attempted", zap.Any("params", userId))

	data, err := h.articleService.QueryArticle(userId, userType)

	if err != nil {
		h.logger.Error("QueryArticle failed", zap.Any("userId", userId), zap.Any("error", err))
		resp.HandleError(ctx, http.StatusInternalServerError, 1, err.Error(), nil)
		return
	}

	resp.HandleSuccess(ctx, data)
}

// 点赞或取消
func (h *articleHandler) LikeArticle(ctx *gin.Context) {
	var params struct {
		UserId    int  `json:"userId"`
		ArticleId int  `json:"articleId"`
		IsLike    bool `json:"islike"`
	}

	if err := ctx.ShouldBind(&params); err != nil {
		h.logger.Warn("LikeArticle", zap.Any("error", err))
		resp.HandleError(ctx, http.StatusBadRequest, 1, err.Error(), nil)
		return
	}

	h.logger.Info("LikeArticle attempted", zap.Any("params", params))

	err := h.articleService.LikeArticle(params.ArticleId, params.UserId, params.IsLike)

	if err != nil {
		h.logger.Error("LikeArticle failed", zap.Any("params", params), zap.Any("error", err))
		resp.HandleError(ctx, http.StatusInternalServerError, 1, err.Error(), nil)
		return
	}

	resp.HandleSuccess(ctx, nil)
}

// 反对或取消反对
func (h *articleHandler) DisLikeArticle(ctx *gin.Context) {
	var params struct {
		UserId    int  `json:"userId"`
		ArticleId int  `json:"articleId"`
		IsDisLike bool `json:"isdisLike"`
	}

	if err := ctx.ShouldBind(&params); err != nil {
		h.logger.Warn("DisLikeArticle", zap.Any("error", err))
		resp.HandleError(ctx, http.StatusBadRequest, 1, err.Error(), nil)
		return
	}

	h.logger.Info("DisLikeArticle attempted", zap.Any("params", params))

	err := h.articleService.DisLikeArticle(params.ArticleId, params.UserId, params.IsDisLike)

	if err != nil {
		h.logger.Error("DisLikeArticle failed", zap.Any("params", params), zap.Any("error", err))
		resp.HandleError(ctx, http.StatusInternalServerError, 1, err.Error(), nil)
		return
	}

	resp.HandleSuccess(ctx, nil)
}

// 收藏、取消收藏文章
func (h *articleHandler) CollectArticle(ctx *gin.Context) {
	var params struct {
		UserId       int  `json:"userId"`
		ArticleId    int  `json:"articleId"`
		IsCollect    bool `json:"isCollect"`
		CollectionId int  `json:"collectionId"`
	}

	if err := ctx.ShouldBind(&params); err != nil {
		h.logger.Warn("CollectArticle", zap.Any("error", err))
		resp.HandleError(ctx, http.StatusBadRequest, 1, err.Error(), nil)
		return
	}

	h.logger.Info("CollectArticle attempted", zap.Any("params", params))

	err := h.articleService.CollectArticle(params.ArticleId, params.UserId, params.IsCollect, params.CollectionId)

	if err != nil {
		h.logger.Error("CollectArticle failed", zap.Any("params", params), zap.Any("error", err))
		resp.HandleError(ctx, http.StatusInternalServerError, 1, err.Error(), nil)
		return
	}

	resp.HandleSuccess(ctx, nil)
}

// 审核文章
func (h *articleHandler) ReviewArticle(ctx *gin.Context) {
	var params struct {
		ArticleIds []int `json:"articleIds"`
		Status     int   `json:"status"`
	}

	if err := ctx.ShouldBind(&params); err != nil {
		h.logger.Warn("ReviewArticle", zap.Any("error", err))
		resp.HandleError(ctx, http.StatusBadRequest, 1, err.Error(), nil)
		return
	}

	h.logger.Info("ReviewArticle attempted", zap.Any("params", params))

	err := h.articleService.ReviewArticle(params.ArticleIds, params.Status)

	if err != nil {
		h.logger.Error("ReviewArticle failed", zap.Any("params", params), zap.Any("error", err))
		resp.HandleError(ctx, http.StatusInternalServerError, 1, err.Error(), nil)
		return
	}

	resp.HandleSuccess(ctx, nil)
}

// 浏览文章
func (h *articleHandler) ViewArticle(ctx *gin.Context) {
	var params struct {
		ArticleId int `json:"articleId"`
	}

	if err := ctx.ShouldBind(&params); err != nil {
		h.logger.Warn("ViewArticle", zap.Any("error", err))
		resp.HandleError(ctx, http.StatusBadRequest, 1, err.Error(), nil)
		return
	}

	err := h.articleService.ViewArticle(params.ArticleId)

	if err != nil {
		h.logger.Error("ViewArticle failed", zap.Any("params", params), zap.Any("error", err))
		resp.HandleError(ctx, http.StatusInternalServerError, 1, err.Error(), nil)
		return
	}

	resp.HandleSuccess(ctx, nil)
}

// 移动文章收藏夹
func (h *articleHandler) MoveArticle(ctx *gin.Context) {
	var params struct {
		ArticleId    int `json:"articleId"`
		CollectionId int `json:"collectionId"`
	}

	if err := ctx.ShouldBind(&params); err != nil {
		h.logger.Warn("MoveArticle", zap.Any("error", err))
		resp.HandleError(ctx, http.StatusBadRequest, 1, err.Error(), nil)
		return
	}

	h.logger.Info("MoveArticle attempted", zap.Any("params", params))

	err := h.articleService.MoveArticle(params.ArticleId, params.CollectionId)

	if err != nil {
		h.logger.Error("MoveArticle failed", zap.Any("ArticleId", params.ArticleId), zap.Any("CollectionId", params.CollectionId), zap.Error(err))
		resp.HandleError(ctx, http.StatusInternalServerError, 1, err.Error(), nil)
		return
	}

	resp.HandleSuccess(ctx, nil)
}

func (h *articleHandler) QueryCollectedArticle(ctx *gin.Context) {
	var params struct {
		UserId       int `form:"userId"`
		CollectionId int `form:"collectionId"`
		Page         int `form:"page"`
		PageSize     int `form:"pageSize"`
	}

	if err := ctx.ShouldBind(&params); err != nil {
		h.logger.Warn("QueryCollectedArticle", zap.Any("error", err))
		resp.HandleError(ctx, http.StatusBadRequest, 1, err.Error(), nil)
		return
	}

	h.logger.Info("QueryCollectedArticle attempted", zap.Any("params", params))

	data, err := h.articleService.QueryCollectedArticle(params.UserId, params.CollectionId, params.Page, params.PageSize)

	if err != nil {
		h.logger.Error("QueryCollectedArticle failed", zap.Any("params", params), zap.Any("error", err))
		resp.HandleError(ctx, http.StatusInternalServerError, 1, err.Error(), nil)
		return
	}

	resp.HandleSuccess(ctx, data)
}

func (h *articleHandler) QueryUserArticle(ctx *gin.Context) {
	var params struct {
		UserId       int `form:"userId"`
		TargetUserId int `form:"targetUserId"`
		Page         int `form:"page"`
		PageSize     int `form:"pageSize"`
	}

	if err := ctx.ShouldBind(&params); err != nil {
		h.logger.Warn("QueryUserArticle", zap.Any("error", err))
		resp.HandleError(ctx, http.StatusBadRequest, 1, err.Error(), nil)
		return
	}

	h.logger.Info("QueryUserArticle attempted", zap.Any("params", params))

	data, err := h.articleService.QueryUserArticle(params.UserId, params.TargetUserId, params.Page, params.PageSize)

	if err != nil {
		h.logger.Error("QueryUserArticle failed", zap.Any("params", params), zap.Any("error", err))
		resp.HandleError(ctx, http.StatusInternalServerError, 1, err.Error(), nil)
		return
	}

	resp.HandleSuccess(ctx, data)
}

func (h *articleHandler) ReviewAllArticle(ctx *gin.Context) {
	err := h.articleService.ReviewAllArticle()
	if err != nil {
		h.logger.Error("QueryUserArticle", zap.Any("error", err))
		resp.HandleError(ctx, http.StatusInternalServerError, 1, err.Error(), nil)
		return
	}

	resp.HandleSuccess(ctx, nil)
}
